
	/***********************************************************************************************
	  
		Module: Encode													-	sid: 1.0
			
		Api:			
		Generic:			
			blob	toBase64		(blob)							- sid: 1.0
			s			fromBase64	(blob)							- sid: 1.0

			json	toJson			(v)									- sid: 1.0
			v			fromJson		(json)							- sid: 1.0

			s			serialize		(obj)								- sid: 1.0
			obj		deserialize	(s)									- sid: 1.0

			node	fromXml			(s)									- sid: 1.0	Parser, Lang
			s			toXml				(node)							- sid: 1.0	Parser, Lang

		Text:			
			blob	toUtf8			(s)									- sid: 1.0
			s			fromUtf8		(blob)							- sid: 1.0
			
			blob	toUtf16			(s, be)							- sid: 1.0
			s			fromUtf16		(blob)							- sid: 1.0
			
			blob	toUtf16BE		(s)									- sid: 1.0
			s			fromUtf16BE	(blob)							- sid: 1.0
			
			blob	toUtf16LE		(s)									- sid: 1.0
			s			fromUtf16LE	(blob)							- sid: 1.0
						
		Compression:			
		  lz77	toLz77			(blob, params)			- sid: 1.0
			blob	fromLz77		(lz77)							- sid: 1.0

		  lzss	toLzss			(blob, params)			- sid: 1.0
			blob	fromLzss		(lzss)							- sid: 1.0
										
	Note: character encoding
			
		Js store the string internally with the UCS-2 encoding scheme
		Js can handle strings in UTF-16 encoding scheme
		In Utf-16 a character can be encoded with 4 bytes (first byte: from 0xD800 to 0xDFFFF)
		A surrogate pair can be inserted into a js string only with literal in a utf-8/utf-16/etc... source script
		or getting the string from the dom with an html page in utf-8/utf-16/etc...
		Not by the \unnnn and not directly append 2 character at the string
		Not by String.fromCharCode()
		A js string with surrogate pairs has a length counting the number of unicode encode point not the number of 
		logical character
																
	***********************************************************************************************/

	//-------------------------------------------------------------------------------
	jsl.Encode = (function() {
		try {
			var mod
			
			mod 					= new jsl.Module("jsl.Encode")
			mod.__b64Map	= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".split("")
			mod.__b64IMap	= {}
			
			jsl.Object.walk(mod.__b64Map, function(id, v) { mod.__b64IMap[v] = id })
			return mod
		}
		catch(e) {
			jsl.throwError(e, "jsl.Encode()")
		}
	})()
	//-------------------------------------------------------------------------------	
	jsl.Encode.toUtf8 = function(s) {
 		try {
			var utf8, c, a, b, len
			
			if(arguments.length !== 1)	throw jsl.ParamError()
			jsl.validate(s, "s", "s")
			
			len		= s.length
			utf8	= []			
			a			= b = 0
			 
			while(a < len) {
	 
				c = s.charCodeAt(a++)
	 			
				//1° - 1 byte of utf-8
				if(c < 128) 
					utf8[b++] = c
				
				//2° - 2 bytes of utf-8
				else if(c < 2048) {
					utf8[b++] = c >> 6 | 192
					utf8[b++] = c & 63 | 128
				}
				//3° - 3 bytes of utf-8 handle 16bit
				else if(c < 0xD800 || c > 0xDFFF) {				
					utf8[b++] = c >> 12 | 224
					utf8[b++] = c >> 6 & 63 | 128
					utf8[b++] = c & 63 | 128
				}	 
				//4° - surrogate pairs, the char is encoded into 4 bytes
				else {
					c = ((c & 0x7FF) << 10) + (s.charCodeAt(a++) & 0x7FF)
					utf8[b++] = c >> 29 | 240
					utf8[b++] = c >> 12 & 63 	| 128
					utf8[b++] = c >> 6 	& 63 	| 128				
					utf8[b++] = c & 63 				| 128				
				}
			}
	 
			return new jsl.Encode.Binary(utf8)			
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
  }
	//-------------------------------------------------------------------------------	
	jsl.Encode.toUtf16 = function(s, be) {
 		try {
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(s, "s", "s")
			if(arguments.length === 2)	jsl.validate(be, "b", "be")
						
			return be !== false ? this.toUtf16BE(String.fromCharCode(0xFEFF) + s) : this.toUtf16LE(String.fromCharCode(0xFFFE) + s)
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
  }
	//-------------------------------------------------------------------------------	
	jsl.Encode.toUtf16BE = function(s) {
 		try {
			var utf16, c, a, b, len
			
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(s, "s", "s")
			
			len		= s.length
			utf16	= []			
			a			= b = 0

			while(a < len) {
				c						= s.charCodeAt(a++)
				utf16[b++] 	=	c >> 8 
				utf16[b++] 	= c & 0xFF
			}			 
	 
			return new jsl.Encode.Binary(utf16)			
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
  }
	//-------------------------------------------------------------------------------	
	jsl.Encode.toUtf16LE = function(s) {
 		try {
			var utf16, c, a, b, len
			
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(s, "s", "s")
			
			len		= s.length
			utf16	= []			
			a			= b = 0

			while(a < len) {
				c						= s.charCodeAt(a++)
				utf16[b++] 	= c & 0xFF 
				utf16[b++] 	= c >> 8 
			}			 
	 
			return new jsl.Encode.Binary(utf16) 			
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
  }
	//@info: this is a binary to text encoding 
	//-------------------------------------------------------------------------------	
	jsl.Encode.toBase64 = function(bin) {
 		try {
			var b64, len, map, a, b, bits, h, m, l, data
			
			if(arguments.length !== 1)							throw jsl.ParamError()	
			if(!(bin instanceof jsl.Encode.Binary))	throw jsl.ParamError("BadType:bin:jsl.Encode.Binary")
				
			//@info: more speed using array than string
			data	= bin.getBytes()
			b64 	= []
			len 	= data.length
			map 	= this.__b64Map	
			a			= b = 0
			
			while(a < len) {
	  		
	  		h = data[a++]
				m = data[a++]
				l = data[a++]							
				
				if(h >= 255)	throw jsl.ParamError("BadValue:data[" + (a - 3) + "]:byte")	
				if(m >= 255)	throw jsl.ParamError("BadValue:data[" + (a - 2) + "]:byte")	
				if(l >= 255)	throw jsl.ParamError("BadValue:data[" + (a - 1) + "]:byte")	
								
				bits 			= h << 16 | m << 8 | l
		  	b64[b++] 	= map[bits >> 18 	& 0x3f]
		  	b64[b++] 	= map[bits >> 12 	& 0x3f]
		  	b64[b++] 	= map[bits >> 6 	& 0x3f]
		  	b64[b++] 	= map[bits 				& 0x3f]
	  	}
			
			if(len % 3 === 1) 			b64[b - 2] = b64[b - 1] = 61
			else if(len % 3 === 2) 	b64[b - 1] = 61

			return new jsl.Encode.Binary(b64)
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
  }
	//-------------------------------------------------------------------------------	 
  jsl.Encode.fromUtf8 = function(bin) {
		try {
			var a, b, c, len, s, fcc, c2, c3, utf8
			
			if(arguments.length !== 1)							throw jsl.ParamError()
			if(!(bin instanceof jsl.Encode.Binary))	throw jsl.ParamError("BadType:bin:jsl.Encode.Binary")

			a 		= b = 0
			utf8 	= bin.getBytes()
			len		=	utf8.length 
			s			= []
			fcc		= String.fromCharCode
			
			while(a < len) {
	 
				c = utf8[a++]
	 			
				//1° byte
				if(c < 128) 
					s[b++] = fcc(c)
					
				//2° byte
				else if(c > 191 && c < 224) {
					c2 = utf8.charCodeAt(a++)
					
					if((c2 & 192) !== 128)	throw jsl.ParamError("BadValue:utf8[" + (a - 1) + "]")
					s[b++] = fcc(((c & 31) << 6) | (c2 & 63))
				}

				//3° byte
				else if(c > 223 && c < 240) {
					c2 = utf8.charCodeAt(a++)
					c3 = utf8.charCodeAt(a++)
					
					if((c2 & 192) !== 128)	throw jsl.ParamError("BadValue:utf8[" + (a - 2) + "]")
					if((c3 & 192) !== 128)	throw jsl.ParamError("BadValue:utf8[" + (a - 1) + "]")

					s[b++] = fcc(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63))
				}
				
				//4° byte not permitted (js use only 16bit)
				else if(c & 0xF8 === 0xF0)	throw jsl.ParamError("utf.UnicodeCharNotSupported:utf8[" + (a - 1) + "]")
				
				//5° error
				else throw jsl.ParamError("BadValue:utf8[" + (a - 1) + "]")
			}
			return s.join("")
		}
		catch(e) {
			jsl.throwError(e, this, arguments)			
		}		
  }
	//-------------------------------------------------------------------------------	 
  jsl.Encode.fromUtf16 = function(bin) {
		try {
			//@info: byte order mark
			var bom, s, utf16
						
			if(arguments.length !== 1)							throw jsl.ParamError()
			if(!(bin instanceof jsl.Encode.Binary))	throw jsl.ParamError("BadType:bin:jsl.Encode.Binary")

			utf16 = bin.getBytes()
			if(utf16.length % 2)										throw jsl.ParamError("BadValue:bin")
			
			if(utf16.length) {
				
				bom = utf16.charCodeAt(0)
				if(bom === 0xFEFF)			s = this.fromUtf16BE(utf16)
				else if(bom === 0xFFFE)	s = this.fromUtf16LE(utf16)
				else										throw jsl.ParamError("utf.BadUtf16Bom")
			}
			else
				s = ""
			
			return s
		}
		catch(e) {
			jsl.throwError(e, this, arguments)			
		}		
  }	
	//-------------------------------------------------------------------------------	 
  jsl.Encode.fromUtf16BE = function(bin) {
		try {
			var a, b, c, len, s, fcc, c2, n, utf16
			
			if(arguments.length !== 1)							throw jsl.ParamError()
			if(!(bin instanceof jsl.Encode.Binary))	throw jsl.ParamError("BadType:bin:jsl.Encode.Binary")

			utf16 = bin.getBytes()
			if(utf16.length % 2)										throw jsl.ParamError("BadValue:bin")
			
			a 	= b = 0
			len	=	utf16.length 
			s		= []
			fcc	= String.fromCharCode
					
			while(a < len) {
	 
				c 			= utf16.charCodeAt(a++)
	 			c2 			= utf16.charCodeAt(a++)
				n				= (c << 8) + c2

				if(n >= 0xD800 && n <= 0xDC00) throw jsl.ParamError("UnicodeCharNotSupported:utf16[" + (a - 2) + "]")
				s[b++]	= fcc(n)								
			}
			return s.join("")
		}
		catch(e) {
			jsl.throwError(e, this, arguments)			
		}		
  }
	//-------------------------------------------------------------------------------	 
  jsl.Encode.fromUtf16LE = function(bin) {
		try {
			var a, b, c, len, s, fcc, c2, n, utf16
			
			if(arguments.length !== 1)							throw jsl.ParamError()
			if(!(bin instanceof jsl.Encode.Binary))	throw jsl.ParamError("BadType:bin:jsl.Encode.Binary")

			utf16 = bin.getBytes()
			if(utf16.length % 2)										throw jsl.ParamError("BadValue:bin")
			
			a 	= b = 0
			len	=	utf16.length 
			s		= []
			fcc	= String.fromCharCode
					
			while(a < len) {
	 
				c 			= utf16.charCodeAt(a++)
	 			c2 			= utf16.charCodeAt(a++)
				n				= (c2 << 8) + c

				if(n >= 0xD800 && n <= 0xDC00) throw jsl.ParamError("UnicodeCharNotSupported:utf16[" + (a - 2) + "]")
				s[b++]	= fcc(n)								
			}
			return s.join("")
		}
		catch(e) {
			jsl.throwError(e, this, arguments)			
		}		
  }
	//-------------------------------------------------------------------------------	 
  jsl.Encode.fromBase64 = function(bin) {
		try {
			var map, fcc, a, b, s, len, bits, b64

			if(arguments.length !== 1)	throw jsl.ParamError()		
			jsl.validate(b64, "s", "b64")
			if(b64.length % 4)																				throw jsl.ParamError("BadValue:b64")
			if(b64.length && !(/^[A-Za-z0-9\+\/]+\={0,2}/).test(b64))	throw jsl.ParamError("BadValue:b64")
			
			map 	= this.__b64IMap	
			fcc 	= String.fromCharCode
			b64		= bin.getBytes()
			len		= b64.length
			a			= b = 0
			s			= []
			
			while(a < len) {
	  		bits 		= map[b64[a++]] << 18 | map[b64[a++]] << 12 | map[b64[a++]] << 6 | map[b64[a++]]
		    s[b++]	= fcc(bits >> 16	& 0xff)
		    s[b++]	= fcc(bits >> 8 	& 0xff)
		    s[b++]	= fcc(bits 				& 0xff)
	  	}			
			
			if(b64[len - 1] === "=") s[b - 1] = ""
			if(b64[len - 2] === "=") s[b - 2] = ""
			
   		return s.join("")
		}
		catch(e) {
			jsl.throwError(e, this, arguments)			
		}		
  }	
	//-------------------------------------------------------------------------------	 
  jsl.Encode.toJson = function(v) {
		try {
			var json, type, f, objs, l, a, c
			
			if(arguments.length !== 1)	throw jsl.ParamError()
			
			json = []
			type = v instanceof Array ? "array" : typeof v
			f.__status++
			
			switch(type) {
				
				//1° - string	
				//-------------------------------------------------------------------------------	 
				case "string":					
					
					json.push("\"")
					for(a = 0, l = v.length; a < l; a++) {
						
						c = v.charCodeAt(a)
						
						//@info: 34=", 92="
						if(c < 0x1f || c === 34 || c === 92)	json.push("\\u" + ("0000" + c.toString(16).slice(-4)))	
						else																	json.push(c)
					}					
					json.push("\"")
					break
				
				//2° - number	
				//-------------------------------------------------------------------------------	 
				case "number":			
					if(isNaN(v))			throw jsl.ParamError("json.NaN:v")
					if(!isFinite(v))	throw jsl.ParamError("json.Infinity:v")
					json.push(v + "")
					break
					
				//3° - boolean	
				//-------------------------------------------------------------------------------	 
				case "boolean":					
					json.push(v ? "true" : "false")
					break
				
				//4° - array	
				//-------------------------------------------------------------------------------	 
				case "array":					
					
					f 		= arguments.callee
					objs 	= f.__objs
					l			= objs.length
					
					for(a = 0; a < l; a++) 
						if(v === objs[a])	throw jsl.ParamError("CircularReference:v")

					f.__objs.push(v)

					json.push("[")
					for(a = 0, l = v.length; a < l; a++) json.concat(f.call(this, v[a]), ",")

					if(json[json.length - 1] === ",")	json[json.length - 1] = "]"
					else 															json.push("]")	
					break

				//5° - object	
				//-------------------------------------------------------------------------------	 
				case "object":
					if(v === null)	json.push("null")
					else {
						
						f 		= arguments.callee
						objs 	= f.__objs
						l			= objs.length
						
						for(a = 0; a < l; a++) 
							if(v === objs[a])	throw jsl.ParamError("CircularReference:v")

						f.__objs.push(v)
						json.push("{")
						
						//@info: some native object can lacks of some Object methods
						for(a in v)
							if(Object.hasOwnProperty.call(v, a)) 							
								json.concat(f.call(this, a), ":", f.call(this, v), ",")
						
						if(json[json.length - 1] === ",")	json[json.length - 1] = "}"
						else 															json.push("}")	
					}
					break
				
				//6° - undefined	
				//-------------------------------------------------------------------------------	 
				default:
					throw jsl.ParamError("json.undefined:v")
			}
			
			f.__status--
			if(!arguments.callee.__status)
				arguments.callee.__objs = []

			return json.join("")
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------	 
	jsl.Encode.toJson.__n 		= -1
	jsl.Encode.toJson.__objs 	= []
	//-------------------------------------------------------------------------------	 
  jsl.Encode.fromJson = function(json) {
		try {
			var idx
			//@d[
			if(arguments.length !== 1)	throw jsl.ParamError()
			jsl.validate(json, "s+", "json")		
			
			//@info: great re pattern for string (with escaping) matching 
			idx = json.replace(/"(\\.|[^"\\])*"/g, "").search(/[^,:{}\[\]0-9.\-+Eeaflnrstu \n\r\t]/)
			
 			if(idx !== -1)	throw jsl.SyntaxError("BadCharacter:json[" + idx + "]")//@d] 

			//@info: 	from ecma specifications -> an expression can not start with the curly bracket '{' because
			//				it can generate ambiguity with open of block         
			jsl.__ni_script_execute("jsl.__vars.tmp.a = (" + json + ")")
			return jsl.__vars.tmp.a 			
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}	
	//-------------------------------------------------------------------------------	 
  jsl.Encode.fromXml = function(xml, unprettify) {
		try {
			var source, node, parent, root, llevel
			
			//@d[							
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(xml, "s+", "xml")
			if(arguments.length === 2)	jsl.validate(unprettify, "b", "unprettify")//@d]

			if(!arguments.callee.__init) {						
				jsl.require("lang")
				arguments.callee.__init = true
			}				
			
			if(unprettify != null && !unprettify.valueOf())
				source = xml	
			
			else
				source = xml.replace(/(<!--[\s\S]*?-->)|("(?:\\.|[^"\\]+)*"|'(?:\\.|[^'\\]+)*')|((?:>\s*\n*<)+)/g, 
					function(token, g1, g2, g3) {
						
						if(g3)	return "><"
						else 		return token
					}) 

			
			llevel 	= 0
			parent	= null
			
			this.__ni_xml_parse(source, function(name, type, value, attributes, level) {
				
				node = new jsl.Node(name)
				node.setType(type + "")
				node.setValue(value)
				node.setAttributes(attributes)
				
				if(level > llevel) 
					parent = lnode

				else if(level < llevel) {
					
					parent = lnode
					
					do{
						parent = parent.getParent() 
						llevel--	
					}while(llevel != level)
					
					parent = parent.getParent()
				}
				
				llevel 	= level
				lnode		= node
								
				if(!root)		root = node	
				if(parent) 	parent.appendChild(node)				
			})
												
			return root
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}	
	//-------------------------------------------------------------------------------	 
  jsl.Encode.toXml = function(node, prettify) {
		try {
			var xml = ""
			
			
			node.walk(function(node) {
				
				xml += "<" + node.getName() + " "				
			})
			
			return xml
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}	

	//-------------------------------------------------------------------------------	 
  jsl.Encode.serialize = function(obj) {
		try {
			var s, f, objs, type, a, own, v, b, l, s2, wki
			//@d[
			if(arguments.length !== 1)	throw jsl.ParamError()
			if(!jsl.isObject(obj))			throw jsl.ParamError("BadType:obj:Object")//@d]
							
			s			= ""
			s2		= ""				
			f 		= arguments.callee 
			objs	= f.__objs
			wki		= f.__wki
			var type = (typeof obj).charAt(0)
				
			if(obj instanceof Array) 				s +=  "a"					
			else if(obj instanceof Date)		s +=  "d" + obj.getTime()  					
			else if(obj instanceof RegExp)	s += ("r" + obj).replace(/#/g, "#0").replace(/@/g, "#1") 
			else if(type === "s") 					s += ("s" + obj).replace(/#/g, "#0").replace(/@/g, "#1")
			else if(type === "n") 					s +=  "n" + obj 
			else if(type === "b") 					s +=  "b" + (obj == "true" ? 1 : 0)
			else if(type === "f") 					s +=  "f" + (obj + "").match(/.*function([\s\S]+)}.*$/)[1].replace(/#/g, "#0").replace(/@/g, "#1") 
			else if(obj.getSerialId instanceof Function && obj.getSerialId()) 
																			s +=  "c" + obj.getSerialId()
			else  													s +=  "o"				
			//no getConstructorName di oggetto  ma interface serializable con metodo getConstructorName
 			//fare anche oggetti String Boolean e Number
/*								
			if(jsl.isArray(obj)) 						s +=  "a"					
			else if(jsl.isDate(obj)) 				s +=  "d" + obj.getTime()  					
			else if(jsl.isRegExp(obj)) 			s += ("r" + obj).replace(/#/g, "#0").replace(/@/g, "#1") 
			else if(jsl.isString(obj)) 			s += ("s" + obj).replace(/#/g, "#0").replace(/@/g, "#1")
			else if(jsl.isNumber(obj)) 			s +=  "n" + obj 
			else if(jsl.isBoolean(obj)) 		s +=  "b" + (obj == "true" ? 1 : 0)
			else if(jsl.isFunction(obj)) 		s +=  "f" + (obj + "").match(/.*function([\s\S]+)}.*$/)[1].replace(/#/g, "#0").replace(/@/g, "#1") 
			else if(obj.getConstructorName && obj.getConstructorName()) 
																			s +=  "c" + obj.getConstructorName()
			else  													s +=  "o"				
	*/			
			objs.push(obj)
			own = Object.prototype.hasOwnProperty 
				
			for(a in obj)
				if(own.call(obj, a) && !wki[a]) {
					
					v	 = obj[a]
					s += "@" + a.replace(/#/g, "#0").replace(/@/g, "#1") + "@"
					
					if(jsl.isObject(v)) {

						for(b = 0, l = objs.length; b < l; b++)
							if(objs[b] === v)
								break
							
						if(b === l) 	
							s2 += f(obj[a])
	
						s += "#" + b
					}
					else 
						if(typeof v === "string") s += "\"" + v.replace(/#/g, "#0").replace(/@/g, "#1") 
						else 											s += v											
				}				
			
			return s + "#" + s2										
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}	
	//-------------------------------------------------------------------------------	 
	jsl.Encode.serialize.__objs		= []
	jsl.Encode.serialize.__wki		= {	//well know id
		constructor: 	true,
		__prototype:	true	
	}
	
	//-------------------------------------------------------------------------------	 
  jsl.Encode.deserialize = function(s) {
		try {
			var objs, data, a, b, id, v, ps, l, l2, ns, obj, f, c
			//@d[
			if(arguments.length !== 1)	throw jsl.ParamError()
			jsl.validate(s, "s+", "s")//@d]
			
			data 	= s.slice(0, -1).split(/#(?!\d)/)
			objs	= []
			
			for(a = 0, l = data.length; a < l; a++) {
				
				//@sys: Explorer 8 - data[a].slice(1).split(/@/) on "@abc..." -> [abc, ...] not ['', abc, ]
				id 			= data[a].charAt(0)
				data[a] = data[a].slice(1).split("@")
				v				= data[a][0]
				
				switch(id) {
					
					case "a":				
						objs[a] = [] 	
						break
					case "d":				
						objs[a] = new Date(parseInt(v)) 	
						break
					case "r":				
						v				= v.replace(/#0/g, "#").replace(/#1/g, "@")
						b				= v.lastIndexOf("/")
						objs[a] = RegExp(v.slice(1, b), v.slice(b + 1)) 	
						break
					case "f":
						v				= v.replace(/#0/g, "#").replace(/#1/g, "@")					
						jsl.__ni_script_execute("jsl.__vars.tmp.a = function" + v + "}") 	
						objs[a] = jsl.__vars.tmp.a 
						break
					case "s":				
						objs[a] = v.replace(/#0/g, "#").replace(/#1/g, "@")
						break
					case "n":				
						objs[a] = parseFloat(v)	
						break
					case "b":				
						objs[a] = Boolean(v === "1") 	
						break
					case "c":
	
						ns	= v.split(".")													
						obj = jsl.__go
						
						for(b = 0, l2 = ns.length; b < l2 - 1; obj = obj[ns[b]], b++)//@d[
							if(!jsl.isObject(obj[ns[b]]))	throw jsl.DataError()//@d]
							;													//ConstructorNotFound no notfound si capisce meglio
						//@d[
						if(!jsl.isFunction(obj[ns[b]]))	throw jsl.NotFoundError("NotFound", [ v ])//@d]								
						
						f						= jsl.__vars.f
						f.prototype = obj[ns[b]].prototype 		
						objs[a] 		= new f 	
						break
					case "o":				
						objs[a] = {} 	
				}
			}			

			for(a = 0; a < l; a++) {
				
				ps = data[a]				
				
				for(b = 1, l2 = ps.length; b < l2; b += 2) {
					
					id		= ps[b].replace(/#0/g, "#").replace(/#1/g, "@")
					v 		= ps[b + 1]					
					c			= v.charAt(0)
										
					switch(c) {
						
						case "\"":
							objs[a][id] = v.slice(1).replace(/#0/g, "#").replace(/#1/g, "@")
							break
						case "t":
						case "f":
							objs[a][id] = c === "t" 
							break
						case "n":
							objs[a][id] = null							
							break
						case "u":
							objs[a][id] = undefined							
							break
						case "#":
							objs[a][id] = objs[v.slice(1)]
							break
						default:
							objs[a][id] = parseFloat(v)												
					}					
				}
			}
			
			return objs[0] 			
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}	
	//-------------------------------------------------------------------------------	 
  jsl.Encode.fromJsc = function(bin) {
		try {
			var bytes, dic, size, out, buffer, pow, bit, a, n, l, idx
			
			size		= bin.__bytes[5] + 1 				
			dic  		= bin.__bytes.slice(6, 6 + size)
			bytes	 	= bin.__bytes.slice(6 + size)		
			out			= []
			pow			= Math.pow
			bit			= 0
			a 			= 1
			n 			= 8
			l 			= bytes.length			
			buffer |= bytes[0] << 16			
			
			while(true) {
															
				bit = (buffer >> 21) & 7 				
				
				if(!bit)
					break
				
				idx = (buffer >> (21 - bit)) & (pow(2, bit) - 1) 	
				
				out.push(dic	[idx])							

				buffer	= buffer << (3 + bit) 
				n 		 -= 3 + bit				

				if(n < 11) 
					if(a < l) {
						buffer |= bytes[a++] << (16 - n)			
						n 		 += 8
					}				
					else if(!n)
						break
			}
			
			return new jsl.Encode.Binary(out)
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------	 
  jsl.Encode.toJsc = function(bin, auto) {
		try {
			var jsc, a, l, bytes, dic, hmap, b, n, i, buffer, c, d, l2, l3, found
			
			bytes = bin.__bytes
			dic		= []
			hmap	= {}
			n			= -1 //da mettere apposto
			
			for(a = 0, l = bytes.length; a < l; a++) {
				
				b = bytes[a]				
								
				if(hmap[b] == null) {
					hmap[b] = { symbol: b, f: 1 }
					dic.push(hmap[b])
					n++
				}				
				else
					hmap[b].f++
			}

			dic.sort(function(b1, b2) { return b2.f - b1.f })
									
			for(a = 0; a < (n+1); a++) {
								
				if(a < 2) 				i	= 1
				else if(a < 4)		i = 2
				else if(a < 8)		i = 3
				else if(a < 16)		i = 4
				else if(a < 32)		i = 5
				else if(a < 64)		i = 6
				else if(a < 128)	i = 7
				else 							i = 8
				 
				dic[a].code	= (i << i) + a
				dic[a].bit	= 3 + i
				dic[a]			= dic[a].symbol
			}
						
			jsc		= new jsl.Encode.Binary([ 35, 106, 115, 99, 35, n ].concat(dic))
			found = false
											
			for(a = 0; a < l; a++) 
				jsc.push(hmap[bytes[a]].code, hmap[bytes[a]].bit)										
			
			return jsc	
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------	 
	jsl.Encode.toJsc.__kws = [		
	
		//if(
		[ 105, 102, 40 ],
		//do{
		[ 100, 111, 123 ],
		//in
		[ 105, 110 ],		
		//for(
		[ 102, 111, 114, 40 ],
		//new
		[ 110, 101, 119 ],		
		//var
		[ 118, 97, 114 ],
		//try{
		[ 116, 114, 121, 123 ],		
		//else
		[ 101, 108, 115, 101 ],		
		//else{
		[ 101, 108, 115, 101, 123 ],		
		//this.
		[ 116, 104, 105, 115, 46 ],		
		//this
		[ 116, 104, 105, 115 ],		
		//true
		[ 116, 114, 117, 101 ],		
		//case
		[ 99, 97, 115, 101 ],
		//void
		[ 118, 111, 105, 100 ],		
		//false
		[ 102, 97, 108, 115, 101 ],		
		//break
		[ 98, 114, 101, 97, 107 ],		

		//function
		[ 102, 117, 110, 99, 116, 105, 111, 110 ],	
		//function(
		[ 102, 117, 110, 99, 116, 105, 111, 110, 40 ],	
		//continue
		[ 99, 111, 110, 116, 105, 110, 117, 101 ],
		//switch(
		[ 115, 119, 105, 116, 99, 104, 40 ],
		//typeof
		[ 116, 121, 112, 101, 111, 102 ],
		//catch(
		[ 99, 97, 116, 99, 104, 40 ],		
		//instanceof
		[ 105, 110, 115, 116, 97, 110, 99, 101, 111, 102 ],		
		//throw
		[ 116, 104, 114, 111, 119 ],		
		//finally{
		[ 102, 105, 110, 97, 108, 108, 121, 123 ],		
		//while(
		[ 119, 104, 105, 108, 101, 40 ],
		//default:
		[ 100, 101, 102, 97, 117, 108, 116, 58 ],		
		//null
		[ 110, 117, 108, 108 ],		
		//with(
		[ 119, 105, 116, 104, 40 ],				
		//delete
		[ 100, 101, 108, 101, 116, 101 ],				
		//return
		[ 114, 101, 116, 117, 114, 110 ],		
		
		//2° - identifiers and properties
		//.hasOwnProperty(
		[ 46 ,104 ,97 ,115 ,79 ,119 ,110 ,80 ,114 ,111 ,112 ,101 ,114 ,116 ,121, 40 ],		
		//.apply(
		[ 46 ,97 ,112 ,112 ,108 ,121, 40 ],		
		//.call(
		[ 46 ,99 ,97 ,108 ,108, 40 ],		
		//.constructor.prototype
		[ 46 ,99 ,111 ,110 ,115 ,116 ,114 ,117 ,99 ,116 ,111 ,114 ,46 ,112 ,114 ,111 ,116 ,111 ,116 ,121 ,112 ,101 ],		
		//.constructor
		[ 46 ,99 ,111 ,110 ,115 ,116 ,114 ,117 ,99 ,116 ,111 ,114 ],		
		//arguments.callee
		[ 97 ,114 ,103 ,117 ,109 ,101 ,110 ,116 ,115 ,46 ,99 ,97 ,108 ,108 ,101 ,101 ],		
		//arguments.length
		[ 97 ,114 ,103 ,117 ,109 ,101 ,110 ,116 ,115 ,46 ,108 ,101 ,110 ,103 ,116 ,104 ],		
		//arguments
		[ 97 ,114 ,103 ,117 ,109 ,101 ,110 ,116 ,115 ],		
		//.length
		[ 46, 108, 101, 110, 103, 116, 104 ],		
		//.prototype.
		[ 46, 112, 114, 111, 116, 111, 116, 121, 112, 101, 46 ],					
		//.prototype
		[ 112, 114, 111, 116, 111, 116, 121, 112, 101 ],					
		//Infinity
		[ 73 ,110 ,102 ,105 ,110 ,105 ,116 ,121 ],
		//undefined
		[ 117 ,110 ,100 ,101 ,102 ,105 ,110 ,101 ,100 ], 
		//NaN
		[ 78 ,97 ,78 ],
		
		//++
		[ 43 ,43 ],		
		
		//--
		[ 45 ,45 ],
		
		//===
		[ 61 ,61 ,61 ],
				
		//==
		[ 61 ,61 ],
		
		//+=
		[ 43 ,61 ],
		
		//-=
		[ 45 ,61 ],

		//!=
		[ 33 ,61 ],
		
		//!==
		[ 33 ,61, 61 ],
		
		//()
		[ 40 ,41 ],
		
		//>=
		[ 62 ,61 ],
		
		//<=
		[ 60 ,61 ],
		
		//&&
		[ 38, 38 ],

		//||
		[ 124, 124 ],
		
		//("
		[ 40, 34 ],
		
		//")
		[ 34, 41 ],
		
		//[]
		[ 91, 93 ],
		
		//{}
		[ 123, 125 ],
		
		//""
		[ 34, 34 ],

		//''
		[ 39, 39 ],
		
		//((
		[ 40, 40 ],
		
		//))
		[ 41, 41 ],
		
		//({
		[ 40, 123 ],
		
		//})
		[ 125, 41 ]
		
		//3° - functions
		//encodeURI
		//isFinite
		//parseFloat
		//escape
		//isNaN
		//parseInt
		//eval
		//decodeURI
		//unescape
		//decodeURIComponent
		
		
		//4° - Built-in types  
		//Object
		//String
		//Array
		//Error
		//SyntaxError
		//Boolean
		//TypeError
		//Date
		//Math
		//RangeError
		//EvalError
		//ReferenceError
		//Function
		//Number
		//RegExp
		//URIError
	]
		
	/*	
	  options:
	  	sbl: 	search buffer length 	(bit)
	  	msl: 	max sequence length		(bit)
	 */
	//-------------------------------------------------------------------------------	 
  jsl.Encode.toLzSS = function(bin, options) {
		try {
			var sbl, sblv, msl, mslv, ks, lzss, bytes, bytes2, i, i2, hm, k, d
					
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(bin, "o", "bin")	
			if(!(bin instanceof jsl.Encode.Binary))				throw jsl.ParamError("BadType:bin:jsl.Encode.Binary")
			
			if(arguments.length === 2) {
				jsl.validate(options, "o", "options")
				if(options.sbl 	!= null)	jsl.validate(options.sbl, "i++", "options.sbl")	
				if(options.msl 	!= null)	jsl.validate(options.msl, "i++", "options.msl")	
			}
						
			sbl		= (options && options.sbl) || 16
			msl		= (options && options.msl) || 7
			sblv	= Math.pow(2, sbl) - 1
			mslv	= Math.pow(2, msl) - 1
			
//			if(sbl + msl + 1 > msl)	throw jsl.ParamError("")
			
			ks		= (sbl + msl + 1) / 8
			ks		= jsl.isInteger(ks) ? ks + 1 : Math.ceil(ks)
			bytes2 = bin.__bytes
			bytes = bin + ""
			lzss	= new jsl.Encode.Binary()
			i			= 0
			i2		= 0
			hm		= {}
			
			if(bytes)
			while(true) {
				
				k = bytes.slice(i, i + ks)
				d = hm[k]
								
				if(d && i - d.i <= sblv) { 										
					
					i2 = i + ks
					
					do {
						
						k += bytes.charAt(i2++)

						if(!hm[k] || (i - hm[k].i > sblv) || !bytes2[i2]) {
							k = k.length === ks ? k : k.slice(0, -1)
							lzss.push((1 << (sbl + msl)) + (i - hm[k].i << msl) + k.length, sbl + msl + 1)
							break
						}
					}	while(true)	
					
					i += k.length		
				}		
				else {
					
					if(d) 
						d.i = i
					else {
						
						i2 = i + k.length
						
						do { 	

							hm[k]  = { i: i, l: k.length }
							k 		+= bytes.charAt(i2++)
							
						} while(k.length <= mslv && bytes2[i2])
					}
					
					lzss.push(bytes2[i], 9)
					i++ 					
				}						

				if(!bytes2[i])
					break				
			}
				
			return lzss		
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}	
	//-------------------------------------------------------------------------------	 
  jsl.Encode.fromLzSS = function(bin, options) {
		try {
			var sbl, sblv, msl, mslv, ks, out, bytes, i, it, f, l , o
			
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(bin, "o", "bin")	
			if(!(bin instanceof jsl.Encode.Binary))				throw jsl.ParamError("BadType:bin:jsl.Encode.Binary")
			
			if(arguments.length === 2) {
				jsl.validate(options, "o", "options")
				if(options.sbl 	!= null)	jsl.validate(options.sbl, "i++", "options.sbl")	
				if(options.msl 	!= null)	jsl.validate(options.msl, "i++", "options.msl")	
			}
						
			sbl		= (options && options.sbl) || 16
			msl		= (options && options.msl) || 7
			sblv	= Math.pow(2, sbl) - 1
			mslv	= Math.pow(2, msl) - 1
			
//			if(sbl + msl + 1 > msl)	throw jsl.ParamError("")
			
			ks		= (sbl + msl + 1) / 8
			ks		= jsl.isInteger(ks) ? ks + 1 : Math.ceil(ks)			
			out		= []
			bytes	= bin.__bytes
									i = 0
			it = bin.getIterator()

			while(it.hasNext()) {
				
				f = it.next(1)
				
				if(!f) 
					out[i++] = (it.next(8))
				else {
					o = it.next(sbl)
					l = it.next(msl)
					
					for(var a = out.length - o, len = out.length - o + l; a < len; a++)
						out[i++] = out[a]
				}
				
			}
			
			return new jsl.Encode.Binary(out)
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}	
	//-------------------------------------------------------------------------------	 
  jsl.Encode.toLz77 = function(bin, options) {
		try {
			var sbl, sblv, msl, mslv, ks, lz77, bytes, i, i2, hm, k
					
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(bin, "o", "bin")	
			if(!(bin instanceof jsl.Encode.Binary))				throw jsl.ParamError("BadType:bin:jsl.Encode.Binary")
			
			if(arguments.length === 2) {
				jsl.validate(options, "o", "options")
				if(options.sbl 	!= null)	jsl.validate(options.sbl, "i++", "options.sbl")	
				if(options.msl 	!= null)	jsl.validate(options.msl, "i++", "options.msl")	
			}
						
			sbl		= (options && options.sbl) || 16
			msl		= (options && options.msl) || 7
			sblv	= Math.pow(2, sbl) - 1
			mslv	= Math.pow(2, msl) - 1
			
			ks		= (sbl + msl) / 8 + 1
			ks		= jsl.isInteger(ks) ? ks + 1 : Math.ceil(ks)

			bytes = bin + ""
			lz77	= new jsl.Encode.Binary()
			i			= 0
			i2		= 0
			hm		= {}
			
			while(true) {
				
				k = bytes.slice(i, i + ks)
				
				if(hm[k] && i - hm[k].i <= sblv) { 										
					
					i += ks
					
					do {
						
						k += bytes.charAt(i++)

						if(!hm[k]) {
							k = k.slice(0, -1)
							lz77.push((i - hm[k].i << (msl + 8)) + (k.length << 8) + bytes.charCodeAt(i), sbl + msl + 8)
							break
						}					
						else if(!bytes[i]) {
							lz77.push(i - hm[k].i, sbl)
							lz77.push(k.length		, msl)
							lz77.push(0					, 8)
							break
						}
					}	while(true)			
				}		
				else {
					
					if(hm[k]) 
						hm[k].i = i
					else {
						
						i2 = i + k.length
						
						while(k.length <= mslv && bytes[i2]) {
	
							hm[k]  = { i: i, l: k.length }
							k 		+= bytes.charAt(i2++)
						} 
					}
					
					lz77.push(bytes.charCodeAt(i), sbl + msl + 8)
					i++ 
					
					if(!bytes[i])
						break
				}						
			}
				
			return lz77			
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}	
	//-------------------------------------------------------------------------------	 
  jsl.Encode.fromLz77 = function(bin, options) {
		try {
			var sbl, msl, size, it, o, l, out, i, bytes
			
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(bin, "o", "bin")	
			if(!(bin instanceof jsl.Encode.Binary))				throw jsl.ParamError("BadType:bin:jsl.Encode.Binary")
			
			if(arguments.length === 2) {
				jsl.validate(options, "o", "options")
				if(options.sbl 	!= null)	jsl.validate(options.sbl, "i++", "options.sbl")	
				if(options.msl 	!= null)	jsl.validate(options.msl, "i++", "options.msl")	
			}
						
			sbl		= (options && options.sbl) || 16	//da mettere costanti in Encode.__LZ77_SEARCH_BUFFER_LENGTH
			msl		= (options && options.msl) || 7
			size	= sbl + msl + 8
			out		= []
			i			= 0
			bytes	= bin.__bytes
									
			it = bin.getIterator()
			
			while(it.hasNext()) {
				
				o = it.next(sbl)				
				
				if(!o) {					
					it.next(msl)
					out.push(it.next(8))
				}
				else {
					l = it.next(msl)
					out.push.apply(out, bytes.slice(i - o, i - o + l))
					out.push(it.next(8))										
				}
				
				i += 3
			}

			return new jsl.Encode.Binary(out)
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}	
	